package com.example.tomatotodo.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.widget.LinearLayout;

import androidx.annotation.Nullable;

import com.example.tomatotodo.R;
import com.example.tomatotodo.model.TodoRecordSyncDTO;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.ValueFormatter;
import com.github.mikephil.charting.listener.ChartTouchListener;
import com.github.mikephil.charting.listener.OnChartGestureListener;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class StatsChartView extends LinearLayout {
    private static final String TAG = "StatsChartView";

    private LineChart chartDuration;
    private BarChart chartCount;
    private LocalDate startDate;
    private LocalDate endDate;
    private List<TodoRecordSyncDTO> records = new ArrayList<>();

    public StatsChartView(Context context) {
        super(context);
        init();
    }

    public StatsChartView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public StatsChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化视图
     */
    private void init() {
        Log.d(TAG, "初始化统计图表视图");
        LayoutInflater.from(getContext()).inflate(R.layout.view_stats_chart, this, true);

        chartDuration = findViewById(R.id.chart_duration);
        chartCount = findViewById(R.id.chart_count);

        setupCharts();
    }

    private void setupCharts() {
        Log.d(TAG, "初始化图表设置");

        // 设置专注时长趋势图
        setupLineChart();

        // 设置完成次数统计图
        setupBarChart();
    }

    private void setupLineChart() {
        chartDuration.getDescription().setEnabled(false);
        chartDuration.setTouchEnabled(true);
        chartDuration.setDragEnabled(true);
        chartDuration.setScaleEnabled(false);
        chartDuration.setPinchZoom(false);
        chartDuration.setDoubleTapToZoomEnabled(false);

        // 禁用除水平方向外的滑动
        chartDuration.setOnChartGestureListener(new OnChartGestureListener() {
            @Override
            public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
            }

            @Override
            public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
            }

            @Override
            public void onChartLongPressed(MotionEvent me) {
            }

            @Override
            public void onChartDoubleTapped(MotionEvent me) {
            }

            @Override
            public void onChartSingleTapped(MotionEvent me) {
            }

            @Override
            public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
            }

            @Override
            public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
            }

            @Override
            public void onChartTranslate(MotionEvent me, float dX, float dY) {
                // 只允许水平方向滑动
                chartDuration.moveViewToX(chartDuration.getLowestVisibleX() - dX);
            }
        });

        XAxis xAxisDuration = chartDuration.getXAxis();
        xAxisDuration.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxisDuration.setGranularity(1f);

        YAxis leftAxisDuration = chartDuration.getAxisLeft();
        leftAxisDuration.setGranularity(1f);
        leftAxisDuration.setAxisMinimum(0f);

        chartDuration.getAxisRight().setEnabled(false);
    }

    private void setupBarChart() {
        chartCount.getDescription().setEnabled(false);
        chartCount.setTouchEnabled(true);
        chartCount.setDragEnabled(true);
        chartCount.setScaleEnabled(false);
        chartCount.setPinchZoom(false);
        chartCount.setDoubleTapToZoomEnabled(false);

        // 禁用除水平方向外的滑动
        chartCount.setOnChartGestureListener(new OnChartGestureListener() {
            @Override
            public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
            }

            @Override
            public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
            }

            @Override
            public void onChartLongPressed(MotionEvent me) {
            }

            @Override
            public void onChartDoubleTapped(MotionEvent me) {
            }

            @Override
            public void onChartSingleTapped(MotionEvent me) {
            }

            @Override
            public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
            }

            @Override
            public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
            }

            @Override
            public void onChartTranslate(MotionEvent me, float dX, float dY) {
                // 只允许水平方向滑动
                chartCount.moveViewToX(chartCount.getLowestVisibleX() - dX);
            }
        });

        XAxis xAxisCount = chartCount.getXAxis();
        xAxisCount.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxisCount.setGranularity(1f);

        YAxis leftAxisCount = chartCount.getAxisLeft();
        leftAxisCount.setGranularity(1f);
        leftAxisCount.setAxisMinimum(0f);

        chartCount.getAxisRight().setEnabled(false);
    }

    /**
     * 设置时间范围
     *
     * @param start 开始日期
     * @param end   结束日期
     */
    public void setDateRange(LocalDate start, LocalDate end) {
        Log.d(TAG, "设置日期范围: " + start + " 至 " + end);
        this.startDate = start;
        this.endDate = end;
    }

    /**
     * 设置数据
     *
     * @param records 记录列表
     */
    public void setData(List<TodoRecordSyncDTO> records) {
        Log.d(TAG, "设置数据，记录数: " + records.size());
        this.records = new ArrayList<>(records);
        processDataAndDrawCharts();
    }

    /**
     * 处理数据并绘制图表
     */
    private void processDataAndDrawCharts() {
        if (startDate == null || endDate == null) {
            Log.w(TAG, "日期范围未设置，无法处理数据");
            return;
        }

        Log.d(TAG, "开始处理数据并绘制图表");

        // 筛选数据
        List<TodoRecordSyncDTO> filteredRecords = filterRecordsByDateRange();

        // 根据时间跨度确定聚合单位
        long daysBetween = endDate.toEpochDay() - startDate.toEpochDay() + 1;
        TimeUnit timeUnit;
        if (daysBetween > 365) {
            timeUnit = TimeUnit.YEAR;
        } else if (daysBetween > 60) {
            timeUnit = TimeUnit.MONTH;
        } else if (daysBetween > 10) {
            timeUnit = TimeUnit.WEEK;
        } else {
            timeUnit = TimeUnit.DAY;
        }

        // 按指定单位分组统计数据
        Map<String, Integer> focusCountByUnit = calculateFocusCountByUnit(filteredRecords, timeUnit);
        Map<String, Integer> focusDurationByUnit = calculateFocusDurationByUnit(filteredRecords, timeUnit);

        // 绘制图表
        drawDurationChartByUnit(focusDurationByUnit, timeUnit);
        drawCountChartByUnit(focusCountByUnit, timeUnit);
    }

    /**
     * 时间单位枚举
     */
    private enum TimeUnit {
        DAY, WEEK, MONTH, YEAR
    }

    /**
     * 根据日期范围筛选记录
     *
     * @return 筛选后的记录列表
     */
    private List<TodoRecordSyncDTO> filterRecordsByDateRange() {
        Log.d(TAG, "筛选指定日期范围内的记录");
        List<TodoRecordSyncDTO> filteredRecords = new ArrayList<>();

        for (TodoRecordSyncDTO record : records) {
            LocalDateTime timeToCheck = record.getEffectiveTime();

            if (timeToCheck != null) {
                LocalDate dateToCheck = timeToCheck.toLocalDate();
                if (!dateToCheck.isBefore(startDate) && !dateToCheck.isAfter(endDate)) {
                    filteredRecords.add(record);
                }
            }
        }

        Log.d(TAG, "筛选后得到 " + filteredRecords.size() + " 条记录");
        return filteredRecords;
    }

    /**
     * 计算指定时间单位的专注次数
     *
     * @param records 记录列表
     * @param unit    时间单位
     * @return 指定时间单位的专注次数映射
     */
    private Map<String, Integer> calculateFocusCountByUnit(List<TodoRecordSyncDTO> records, TimeUnit unit) {
        Log.d(TAG, "计算按 " + unit + " 聚合的专注次数");
        Map<String, Integer> countByUnit = new HashMap<>();

        for (TodoRecordSyncDTO record : records) {
            // 判断是否为不计时记录
            boolean isNoTimerRecord = Boolean.TRUE.equals(record.getFinished())
                    && record.getEndTime() != null
                    && record.getStartTime() != null
                    && record.getEndTime().isBefore(record.getStartTime());

            // 不计时记录不计入次数统计
            if (!isNoTimerRecord) {
                LocalDateTime timeToCheck = record.getEffectiveTime();

                if (timeToCheck != null) {
                    LocalDate date = timeToCheck.toLocalDate();
                    String unitKey = getUnitKey(date, unit);
                    countByUnit.put(unitKey, countByUnit.getOrDefault(unitKey, 0) + 1);
                }
            }
        }

        Log.d(TAG, "完成次数统计计算，共 " + countByUnit.size() + " 个时间单位有记录");
        return new TreeMap<>(countByUnit); // 按键排序
    }

    /**
     * 计算指定时间单位的专注时长
     *
     * @param records 记录列表
     * @param unit    时间单位
     * @return 指定时间单位的专注时长映射（秒）
     */
    private Map<String, Integer> calculateFocusDurationByUnit(List<TodoRecordSyncDTO> records, TimeUnit unit) {
        Log.d(TAG, "计算按 " + unit + " 聚合的专注时长");
        Map<String, Integer> durationByUnit = new HashMap<>();

        for (TodoRecordSyncDTO record : records) {
            // 判断是否为不计时记录
            boolean isNoTimerRecord = Boolean.TRUE.equals(record.getFinished())
                    && record.getEndTime() != null
                    && record.getStartTime() != null
                    && record.getEndTime().isBefore(record.getStartTime());

            // 不计时记录不计入时长统计
            if (!isNoTimerRecord) {
                LocalDateTime timeToCheck = record.getEffectiveTime();

                if (timeToCheck != null) {
                    LocalDate date = timeToCheck.toLocalDate();
                    String unitKey = getUnitKey(date, unit);
                    int duration = record.getActualFocusSeconds() != null ? record.getActualFocusSeconds() : 0;
                    durationByUnit.put(unitKey, durationByUnit.getOrDefault(unitKey, 0) + duration);
                }
            }
        }

        Log.d(TAG, "专注时长统计计算，共 " + durationByUnit.size() + " 个时间单位有记录");
        return new TreeMap<>(durationByUnit); // 按键排序
    }

    /**
     * 获取指定时间单位的键
     *
     * @param date 日期
     * @param unit 时间单位
     * @return 时间单位键
     */
    private String getUnitKey(LocalDate date, TimeUnit unit) {
        switch (unit) {
            case YEAR:
                return String.valueOf(date.getYear());
            case MONTH:
                return date.getYear() + "-" + String.format("%02d", date.getMonthValue());
            case WEEK:
                return date.getYear() + "-W" + String.format("%02d", date.getDayOfYear() / 7 + 1);
            case DAY:
            default:
                return date.toString();
        }
    }

    /**
     * 绘制专注时长趋势图（按时间单位）
     *
     * @param durationByUnit 指定时间单位的专注时长数据
     * @param timeUnit       时间单位
     */
    private void drawDurationChartByUnit(Map<String, Integer> durationByUnit, TimeUnit timeUnit) {
        Log.d(TAG, "[ui] 绘制专注时长趋势图（按" + timeUnit + "聚合）");

        List<Entry> entries = new ArrayList<>();
        List<String> xLabels = new ArrayList<>();

        int index = 0;
        for (Map.Entry<String, Integer> entry : durationByUnit.entrySet()) {
            // 将秒转换为分钟显示
            float minutes = entry.getValue() / 60.0f;
            entries.add(new Entry(index, minutes));
            xLabels.add(formatUnitKeyForXAxis(entry.getKey(), timeUnit));
            index++;
        }

        LineDataSet dataSet = new LineDataSet(entries, "专注时长(分钟)");
        dataSet.setColor(getResources().getColor(R.color.accent_color));
        dataSet.setCircleColor(getResources().getColor(R.color.accent_color));
        dataSet.setLineWidth(2f);
        dataSet.setCircleRadius(4f);
        dataSet.setDrawValues(false);

        LineData lineData = new LineData(dataSet);
        chartDuration.setData(lineData);

        // 设置X轴标签
        XAxis xAxis = chartDuration.getXAxis();
        xAxis.setValueFormatter(new ValueFormatter() {
            @Override
            public String getFormattedValue(float value) {
                int intValue = (int) value;
                if (intValue >= 0 && intValue < xLabels.size()) {
                    return xLabels.get(intValue);
                }
                return "";
            }
        });

        chartDuration.invalidate(); // 刷新图表
    }

    /**
     * 绘制完成次数统计图（按时间单位）
     *
     * @param countByUnit 指定时间单位的完成次数数据
     * @param timeUnit    时间单位
     */
    private void drawCountChartByUnit(Map<String, Integer> countByUnit, TimeUnit timeUnit) {
        Log.d(TAG, "[ui] 绘制完成次数统计图（按" + timeUnit + "聚合）");

        List<BarEntry> entries = new ArrayList<>();
        List<String> xLabels = new ArrayList<>();

        int index = 0;
        for (Map.Entry<String, Integer> entry : countByUnit.entrySet()) {
            entries.add(new BarEntry(index, entry.getValue()));
            xLabels.add(formatUnitKeyForXAxis(entry.getKey(), timeUnit));
            index++;
        }

        BarDataSet dataSet = new BarDataSet(entries, "完成次数");
        dataSet.setColor(getResources().getColor(R.color.accent_color));
        dataSet.setDrawValues(false);

        BarData barData = new BarData(dataSet);
        chartCount.setData(barData);

        // 设置X轴标签
        XAxis xAxis = chartCount.getXAxis();
        xAxis.setValueFormatter(new ValueFormatter() {
            @Override
            public String getFormattedValue(float value) {
                int intValue = (int) value;
                if (intValue >= 0 && intValue < xLabels.size()) {
                    return xLabels.get(intValue);
                }
                return "";
            }
        });

        chartCount.invalidate(); // 刷新图表
    }

    /**
     * 格式化时间单位键用于X轴显示
     *
     * @param unitKey  时间单位键
     * @param timeUnit 时间单位
     * @return 格式化后的字符串
     */
    private String formatUnitKeyForXAxis(String unitKey, TimeUnit timeUnit) {
        switch (timeUnit) {
            case YEAR:
                return unitKey; // 显示年份，如 "2023"
            case MONTH:
                // 从 "2023-08" 格式中提取月份，显示为 "08"
                String[] parts = unitKey.split("-");
                if (parts.length == 2) {
                    return parts[1];
                }
                return unitKey;
            case WEEK:
                // 从 "2023-W32" 格式中提取周数，显示为 "W32"
                String[] weekParts = unitKey.split("-W");
                if (weekParts.length == 2) {
                    return "W" + weekParts[1];
                }
                return unitKey;
            case DAY:
            default:
                // 从 "2023-08-15" 格式中提取月日，显示为 "08-15"
                String[] dateParts = unitKey.split("-");
                if (dateParts.length == 3) {
                    return dateParts[1] + "-" + dateParts[2];
                }
                return unitKey;
        }
    }

    /**
     * 清理资源，避免内存泄漏
     */
    public void clear() {
        Log.d(TAG, "clear: 清理图表资源");
        if (chartDuration != null) {
            chartDuration.clear();
        }
        if (chartCount != null) {
            chartCount.clear();
        }
    }
}
